昨天習得 事件 、 轉移 的概念後,讓我們來思考實作這個 transition,還需要什麼東西?
transition('待付款', '收到帳款') === '待發貨'
transition('站立', '按 B') === '跳躍'
或者說我們這個主體、狀態至轉移的過程,還欠缺什麼東西?
訂單:提交 → 待付款 → 待發貨→ 待取件→ 交易完成
角色移動模組:站 → 跳 → 站
以 RPG 遊戲的角色移動模組為例,玩家開始操縱角色前,一定要會有個初始狀態,可能是來自上次離線的紀錄(等級、hp,mp, sp, attack, speed..)或是初心者最開始的狀態。
而以電商訂單為例,訂單最開始一定會有提交階段吧,由消費者向廠商提出購買的意願、詢問是否有貨源等等,當有了這個最開始的條件,我們才能確認、有辦法繼續往後面處理一系列的交易流程。
所以這個主體也必須要有一個初始值,我們稱做初始狀態 (Initial State)
以 RPG 遊戲的角色移動模組為例,玩家開始操縱角色後,什麼代表著結束?可能是玩家決定登出、角色HP歸零死亡,遊戲破關等等...或者是玩家移動到一個安全的地方,然後把電腦繼續開著掛機,不會結束。
而以電商訂單為例,怎麼樣可以視一張訂單為結束?
可以是產品送達客戶後的交易完成、或是客戶決定取消下單、或供應商沒貨的交易取消、或是使用者忘記期限內付費的交易失效等等。
我們稱這個主體被結束時,所處的狀態稱作結束狀態 (Final State"s")
所以我們大致觀察一直以來的這兩個範例需求中的一些特徵
by The Finite State of Reactive Animations
一個主體、物件底下所存在的狀態們、事件,以及轉換的這個旅程,我們稱作一個有限狀態機(Finite State Machine)。
至於為什麼狀態機前多了前綴字「有限」
我想可以用這句話理解: 因為要有 Transition 這張表的存在,必須記錄 什麼事件 + 什麼狀態 = 轉換後的狀態
,因為要把它們列舉出來,前述的狀態與事件的數量就會是有限的。
原因便是我們在規劃一個物件、系統流程時,底下有太多不同種的狀態,還有各自的條件限制,為了滿足系統與規格的需求,假如我們只單純使用 if/else
block 並設計幾個 flag isSomething/isOtherthing
隨著系統擴充、調整,可能會為我們帶來麻煩。
假設我的功能新增 也是繼續增加 if/else
或是增加 flag isC/hasD
等等,我們會面臨到,必須回去其他檢查舊有的 if/else block ,思考新增的狀態跟舊狀態有沒有什麼相依性、或是防禦 (Guard) 要處理,違反了開放封閉原則 ,專案程式碼也變得難以閱讀。
雖然上述的寫法很簡單、很快速,我們的程式碼也能非常自由的靈活運用,但代價就是過於自由,變得難以顧及整體。
限制你總體狀態的有哪些、可以有哪些事件存在,什麼事件配什麼狀態能進行狀態轉移 → 有限狀態機 ( Finite State Machine )
所以如果當你的需求是一個複雜狀態的情境時,在系統規劃上,你便可以考慮使用有限狀態機
結束狀態 (Final State"s")
這裡特別強調 "s" 是指有多種結束狀態嗎?
5.有限數量的結束狀態( 0 - n 個 )
對,就是後面提到的,結束狀態可能會有 0 - n 個
有可能不會有結束狀態,也有可能有多個結束狀態